#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<boost/filesystem.hpp>
#include"util.hpp"

//设置字体颜色
#ifndef COLOR
#define COLOR
#define RESET "\033[0m"
#define RED "\033[31m"    /* Red */
#define GREEN "\033[32m"   /* Green */
#endif

const std::string src_path = "data/input/";             //待处理的html文件路径
const std::string output = "data/raw_html/raw.txt";     //解析html之后的文件保存路径

//参数类型说明
//const&:   输入型参数
//*:        输出型参数
//&:        输入输出型参数

struct DocInfo_t {
    std::string title;      //文档标题
    std::string content;    //文档内容
    std::string url;        //文档在官网中的url
};

//递归式的把每一个文件名带路径，保存在files_list中，方便进行文件的读取
bool EnumFile(const std::string& src_path, std::vector<std::string>* files_list) {
    namespace fs = boost::filesystem;
    fs::path root_path(src_path);

    //判断路径是否有效
    if (!fs::exists(root_path)) {
        std::cerr << RED << src_path << " is not exists!" << RESET << std::endl;
        return false;
    }

    //定义一个空迭代器，用来判断递归结束
    fs::recursive_directory_iterator end;
    for (fs::recursive_directory_iterator iter(root_path); iter != end; ++iter) {
        //如果不是普通文件，跳过
        if (!fs::is_regular_file(*iter)) {
            continue;
        }
        //如果是普通文件，根据后缀找到我们需要的.html文件，放入files_list
        if (iter->path().extension() != ".html") {
            continue;
        }
        //std::cout << iter->path().string() << std::endl;
        files_list->emplace_back(iter->path().string());
    }

    return true;
}

//解析title
static bool ParseTitle(const std::string& file, std::string* title) {
    size_t begin = file.find("<title>");
    if (begin == std::string::npos) {
        return false;
    }
    size_t end = file.find("</title>");
    if (end == std::string::npos) {
        return false;
    }
    begin += std::string("<title>").size();
    *title = file.substr(begin, end - begin);
    return true;
}

//解析content
static bool ParseContent(const std::string& file, std::string* content) {
    //设置一个简易的状态机      LABLE表示标签   CONTENT表示我们需要的内容
    enum Status{
        LABLE,
        CONTENT
    };

    Status status = LABLE;
    //只需要CONTENT
    for (char c : file) {
        switch(status) {
            case LABLE:
                if (c == '>') {
                    status = CONTENT;
                }
                break;
            case CONTENT:
                if (c == '<') {
                    status = LABLE;
                }
                else {
                    //不要\n，因为要用\n作为每一个html文件解析后的分隔符
                    if (c == '\n') {
                        c = ' ';
                    }
                    content->push_back(c);
                }
                break;
            default:
                break;
        }
    }
    return true;
}

//解析url
static bool ParseUrl(const std::string& file_path, std::string* url) {
    std::string url_head = "https://www.boost.org/doc/libs/1_81_0/doc/html/";
    std::string url_tail = file_path.substr(src_path.size());
    *url = url_head + url_tail;
    return true;
}

static void ShowDoc(const DocInfo_t& doc) {
    std::cout << "Title: " << doc.title << std::endl;
    std::cout << "Content: " << doc.content << std::endl;
    std::cout << "Url: " << doc.url << std::endl;
}
//读取每个文件内容，并进行解析
bool ParseHtml(const std::vector<std::string>& files_list, std::vector<DocInfo_t>* results) {
    for (const std::string& file : files_list) {
        //1.读取文件
        std::string result;
        if (!ns_util::FileUtil::ReadFile(file, &result)) {
            std::cout << file << std::endl;
            std::cerr << RED << "Read File error!" << RESET << std::endl;
            continue;
        }

        DocInfo_t doc;
        //2.解析文件，提取tile
        if (!ParseTitle(result, &doc.title)) {
            std::cout << file << std::endl;
            std::cerr << RED << "Parse title error!" << RESET << std::endl;
            continue;
        }
        //3.解析文件，提取content
        if (!ParseContent(result, &doc.content)) {
            std::cout << file << std::endl;
            std::cerr << RED << "Parse content error!" << RESET << std::endl;
            continue;
        }
        //4.解析文件路径，构建url
        if (!ParseUrl(file, &doc.url)) {
            std::cout << file << std::endl;
            std::cerr << RED << "Parse url error!" << RESET << std::endl;
            continue;
        }
        //解析成功
        results->emplace_back(doc);

        //调试一下
        // std::cout << "调试一下:" << std::endl;
        // ShowDoc(doc);
        // break;
    }
    return true;
}

//把解析之后的各个文件内容写入到ouput中，按照\3作为每个文档的分隔符
bool SaveHtml(const std::vector<DocInfo_t>& results, const std::string& output) {
    //按二进制的方式进行写入
    std::ofstream out(output, std::ios::binary | std::ios::out);
    if (!out.is_open()) {
        std::cerr << RED << output << " open failed!" << RESET << std::endl;
        return false;
    }
    //打开成功，进行文件内容写入
    for (const DocInfo_t& doc : results) {
        std::string s;
        s.append(doc.title);
        s.push_back('\3');
        s.append(doc.content);
        s.push_back('\3');
        s.append(doc.url);
        s.push_back('\n');
        //将字符串写入文件
        out.write(s.c_str(), s.size());
    }

    //关闭文件
    out.close();
    return true;
}